#include <jni.h>

#include "android/log.h"
#include "pedometer.h"
#include "StepCounter.h"
#include "StepDetector.h"
#include <string.h>

#define TAG    "jni-test"

#define  LOGI(...)  __android_log_print(ANDROID_LOG_INFO,LOG_TAG,__VA_ARGS__)
#define  LOGE(...)  __android_log_print(ANDROID_LOG_ERROR,TAG,__VA_ARGS__)
extern "C"{
#if 1
/*
 * Class:     com_goodving_pedometer_StepCounter
 * Method:    getSamplingRate
 * Signature: ()I
 */
JNIEXPORT jint JNICALL Java_com_goodving_pedometer_StepCounter_getSamplingRate
        (JNIEnv * env, jclass paraClass)
{
    MotionDetector *pMonIns;
    return pMonIns->getInstance()->get();

}

/*
 * Class:     com_goodving_pedometer_StepCounter
 * Method:    motionDetectorUpdate
 * Signature: (JDDD)V
 */
JNIEXPORT void JNICALL Java_com_goodving_pedometer_StepCounter_motionDetectorUpdate
        (JNIEnv *, jclass, jlong time, jdouble xAxis, jdouble yAxis, jdouble zAxis)
{
    MotionDetector *pMonIns = 0;
    RawData * pRaw = new RawData(time, xAxis, yAxis, zAxis);

    pMonIns->getInstance()->update(pRaw);
}

/*
 * Class:     com_goodving_pedometer_StepCounter
 * Method:    readStepCounter
 * Signature: ()J
 */
JNIEXPORT jlong JNICALL Java_com_goodving_pedometer_StepCounter_readStepCounter
        (JNIEnv *, jclass)
{
    StepCounter *pCntIns; // r0@1
    return pCntIns->getInstance()->get();
}

/*
 * Class:     com_goodving_pedometer_StepCounter
 * Method:    smoothFilterUpdate
 * Signature: (JDDD)D
 */
JNIEXPORT jdouble JNICALL Java_com_goodving_pedometer_StepCounter_smoothFilterUpdate
        (JNIEnv *, jclass, jlong time, jdouble xAxis, jdouble yAxis, jdouble zAxis)
{
    SmoothFilter *pFilterIns = 0;

    RawData * pRaw = new RawData(time, xAxis, yAxis, zAxis);

    pFilterIns->getInstance()->update(pRaw);
    return pFilterIns->getInstance()->get()->accelerator;

}


/*
 * Class:     com_goodving_pedometer_StepCounter
 * Method:    stepDetectorUpdate
 * Signature: ()Z
 */
JNIEXPORT jboolean JNICALL Java_com_goodving_pedometer_StepCounter_stepDetectorUpdate
        (JNIEnv *, jclass)
{
    SmoothFilter *pFilterIns = 0;
    ThresholdCalculator *pThresIns = 0;
    StepDetector *pStepIns = 0;
    StepCounter *pCntIns = 0;
    int result = 0;

    if(pStepIns->getInstance()->update(pFilterIns->getInstance()->get()))
    {
        pCntIns->getInstance()->update(*pStepIns->getInstance()->get());
        result = 1;
    }

    return result;
}


/*
 * Class:     com_goodving_pedometer_StepCounter
 * Method:    stillDetectorUpdate
 * Signature: ()V
 */
JNIEXPORT void JNICALL Java_com_goodving_pedometer_StepCounter_stillDetectorUpdate
        (JNIEnv *, jclass)
{
    SmoothFilter *pFilterIns = 0;
    MotionDetector *pMonIns = 0;
    ThresholdCalculator *pThresIns = 0;

    pMonIns->getInstance()->update(pFilterIns->getInstance()->get()->time ,
                                          pThresIns->getInstance()->getDeviation());

}

/*
 * Class:     com_goodving_pedometer_StepCounter
 * Method:    thresholdCalculatorRead
 * Signature: ()D
 */
JNIEXPORT jdouble JNICALL Java_com_goodving_pedometer_StepCounter_thresholdCalculatorRead
        (JNIEnv *, jclass)
{
    ThresholdCalculator *pThresIns = 0;

    return pThresIns->getInstance()->getDeviation();
}


/*
 * Class:     com_goodving_pedometer_StepCounter
 * Method:    thresholdCalculatorUpdate
 * Signature: ()Z
 */
JNIEXPORT jboolean JNICALL Java_com_goodving_pedometer_StepCounter_thresholdCalculatorUpdate
        (JNIEnv *, jclass)
{
    SmoothFilter *pFilterIns = 0;
    ThresholdCalculator *pThresIns = 0;

    return pThresIns->getInstance()->update(pFilterIns->getInstance()->get());

}

JNIEXPORT jint JNICALL Java_com_goodving_pedometer_StepCounter_updateStepCounter
        (JNIEnv *env, jclass paraClass, jlong time, jdouble xAxis, jdouble yAxis, jdouble zAxis)
{
#if 0

	return 1;

#else
    int result = 0;
    RawData * pRaw;
    MotionDetector * pMonIns;
    Interpolator *pPolatorIns;
    SmoothFilter *pFilterIns;
    ThresholdCalculator *pThresIns;
    StepDetector* pStepIns;
    StepCounter* pCntIns;

    pMonIns = pMonIns->getInstance();
    pPolatorIns = pPolatorIns->getInstance();
    pFilterIns = pFilterIns->getInstance();
    pThresIns = pThresIns->getInstance();
    pStepIns = pStepIns->getInstance();
    pCntIns = pCntIns->getInstance();

    pRaw = new RawData(time, xAxis, yAxis, zAxis);
    //v10 = a3;
    //v11 = RawData::RawData((int)&v63, a3, a5, a6, a7, a8, a9, a10);
    pMonIns->update(pRaw);
    //v12 = (MotionDetector *)MotionDetector::getInstance((MotionDetector *)v11);
    // make the v13 equal to the status of current motion detector
    // 1. insert the rawdata to the motiondector
    // 2. return the status to V13.
    //pMon->update(pRaw);
    //v13 = MotionDetector::update(v12, (const RawData *)&v63);
    //1. insert the rawdata to the interpolator
    //2. get the return value if it is 0 then ignore one calculation.
    if(!(pPolatorIns->update(pRaw)))
        goto LABEL_17;
    //if the timestamp is 0 then go to label17 directly.
    // v17 point to a interprolator, and which is the first 80 bytes of the smoothfilter
    pFilterIns->update(pPolatorIns->get());

    // update the smoothfilter to process the rawdata then give to the threshold calculate

    if(pThresIns->update(pFilterIns->get()))
    {
        pMonIns->update(pPolatorIns->get()->time, pThresIns->getDeviation());
    }

    // use the raw data which processed by the smoothfilter to update the stepdetector
    if(pStepIns->update(pFilterIns->get()))
    {
        result = pCntIns->update(*pStepIns->get());
    } else {
        LABEL_17:
        result = 0;
    }

    // use the smoothfilter to process the rawdata then update the threshold.
    pFilterIns->update(pRaw);

    if(pThresIns->update(pFilterIns->get()))
    {
        pMonIns->update(time, pThresIns->getDeviation());
    }

//  // if over the threshold then get the deviation and udpate the motion detector

    if(pStepIns->update(pFilterIns->get()))
    {
        if(pCntIns->update(*pStepIns->get()))
            result = 1;
    }

    return result;
#endif
}

JNIEXPORT void JNICALL Java_com_goodving_pedometer_StepCounter_writeStepCounter
        (JNIEnv *, jclass, jlong step)
{
    StepCounter * pCntIns;

    pCntIns->getInstance()->set(step);
}
#else

JNIEXPORT jint JNICALL Java_com_goodving_pedometer_StepCounter_updateStepCounter
        (JNIEnv *env, jclass paraClass, jlong time, jdouble xAxis, jdouble yAxis, jdouble zAxis)
{


	return 1;
}
#endif
}
